#include<conio.h>
#include<math.h>
#include<GL/glut.h>
#include<stdlib.h>

#define white 1
#define black 0
#define MAXX 400
#define MAXY 400
#define MARGINX 40
#define MARGINY 40
#define FRICTION 0.02
#define startgame 0
#define menu 1
#define strikermove 2
#define direction 3
#define powerfunc 4
#define play 5
#define carrommargin 70
#define true 1
#define false 0

struct cord
{
       float x,y;
}vel[20],pos[20],cross;
int player= black;
float radius[20];
int event=startgame;
int colour_black = 0, colour_white = 0; 
int power = 110;

void initialize()
{
    
     int i;
     for(i=0;i<20;i++)
     {
                     vel[i].x=0;vel[i].y=0;
                     radius[i]=MAXX/30;
     }
        pos[0].x = MARGINX+MAXX/2 - 2*radius[0];	    pos[0].y = MARGINY + MAXX/2 - 2*1.731*radius[0];
        pos[1].x = MARGINX+MAXX/2 + 2*radius[0];	    pos[1].y = MARGINY + MAXX/2 - 2*1.731*radius[0];
        pos[2].x = MARGINX+MAXX/2 - 1*radius[0];	    pos[2].y = MARGINY + MAXX/2 - 1*1.731*radius[0];
        pos[3].x = MARGINX+MAXX/2 - 4*radius[0];	    pos[3].y = MARGINY + MAXX/2 - 0*1.731*radius[0];
        pos[4].x = MARGINX+MAXX/2 + 2*radius[0];	    pos[4].y = MARGINY + MAXX/2 - 0*1.731*radius[0];
        pos[5].x = MARGINX+MAXX/2 + 4*radius[0];	    pos[5].y = MARGINY + MAXX/2 - 0*1.731*radius[0];
        pos[6].x = MARGINX+MAXX/2 - 1*radius[0];	    pos[6].y = MARGINY + MAXX/2 + 1*1.731*radius[0];
        pos[7].x = MARGINX+MAXX/2 - 2*radius[0];	    pos[7].y = MARGINY + MAXX/2 + 2*1.731*radius[0];
        pos[8].x = MARGINX+MAXX/2 + 2*radius[0];	    pos[8].y = MARGINY + MAXX/2 + 2*1.731*radius[0];
        
        pos[9].x = MARGINX+MAXX/2 - 0*radius[0];	    pos[9].y = MARGINY + MAXX/2 - 2*1.731*radius[0];
        pos[10].x = MARGINX+MAXX/2 - 3*radius[0];	pos[10].y = MARGINY + MAXX/2 - 1*1.731*radius[0];
        pos[11].x = MARGINX+MAXX/2 + 1*radius[0];	pos[11].y = MARGINY + MAXX/2 - 1*1.731*radius[0];
        pos[12].x = MARGINX+MAXX/2 + 3*radius[0];	pos[12].y = MARGINY + MAXX/2 - 1*1.731*radius[0];
        pos[13].x = MARGINX+MAXX/2 - 2*radius[0];  	pos[13].y = MARGINY + MAXX/2 - 0*1.731*radius[0];
        pos[14].x = MARGINX+MAXX/2 - 3*radius[0];	pos[14].y = MARGINY + MAXX/2 + 1*1.731*radius[0];
        pos[15].x = MARGINX+MAXX/2 + 1*radius[0];	pos[15].y = MARGINY + MAXX/2 + 1*1.731*radius[0];
        pos[16].x = MARGINX+MAXX/2 + 3*radius[0];	pos[16].y = MARGINY + MAXX/2 + 1*1.731*radius[0];
        pos[17].x = MARGINX+MAXX/2 - 0*radius[0];	pos[17].y = MARGINY + MAXX/2 + 2*1.731*radius[0];
        
        pos[18].x = MARGINX+MAXX/2;	            pos[18].y = MARGINY + MAXX/2;
        pos[19].x = MARGINX+MAXX/2;             pos[19].y = MARGINY + carrommargin + MAXX/24;
        
        radius[19]=MAXX/24;
}

void myinit(void)
{
    glClearColor(0.0, 0.0, 0.0, 0.0); /* gray background */
    glShadeModel(GL_SMOOTH);
    glMatrixMode(GL_PROJECTION);      /* In World coordinates: */
    glLoadIdentity();                 /* position the "clipping rectangle" */
    gluOrtho2D(0,640,0,480);
    glMatrixMode(GL_MODELVIEW);       /* edge at -B/2 and its top edge at +B/2 */
}

void draw_board()
{
     int i,j;
     glClear(GL_COLOR_BUFFER_BIT);
     glMatrixMode(GL_MODELVIEW);
     glLoadIdentity();
     
     glColor3f(0.1,0.7,0.6);
     glBegin(GL_POLYGON);
     glVertex2f(MARGINX,MARGINY);
     glVertex2f(MARGINX+MAXX,MARGINY);
     glVertex2f(MARGINX+MAXX,MARGINY+MAXY);
     glVertex2f(MARGINX,MARGINY+MAXY);
     glEnd();
     
     for(i=0;i<19;i++)
     {
               glBegin(GL_POLYGON);
               if(i<9)
                      glColor3f(0.8,0.8,0.8);
               else if(i<18)
                      glColor3f(0.2,0.2,0.2);
               else
                   glColor3f(0.9,0.2,0.2);
                      
               
               for(j=0;j<40;j++)
               {
                                glVertex3f(pos[i].x+radius[i]*cos(3.14*j/20),pos[i].y+radius[i]*sin(3.14*j/20),0);
               }
               glEnd();
     }
     glBegin(GL_POLYGON);
     if(player == white)
     glColor3f(1.0,1.0,1.0);
     else
     glColor3f(1.0,0.0,1.0);
     for(j=0;j<40;j++)
     {
                      glVertex3f(pos[19].x+radius[19]*cos(3.14*j/20),pos[19].y+radius[19]*sin(3.14*j/20),0);
     }
     glEnd();
     
     if(event==direction || event==powerfunc)
     {
     glColor3f(0.0,0.0,0.0);
     glLineWidth(3);
     glBegin(GL_LINES);
     glVertex2f(cross.x+10,cross.y+10);
     glVertex2f(cross.x-10,cross.y-10);
     glVertex2f(cross.x+10,cross.y-10);
     glVertex2f(cross.x-10,cross.y+10);
     glEnd();
     }
     glutSwapBuffers();
}
void striker_set()
{  
      pos[19].x = MARGINX+MAXX/2;             pos[19].y = MARGINY + carrommargin + MAXX/24; //radius[19] = MAXX/24;
      int i;
      for(i=0;i<19;i++)
      {
                       while(sqrt(pow(pos[19].x-pos[i].x,2)+pow(pos[19].y-pos[i].y,2))< radius[19]+radius[i])
                       {
                                       if(pos[i].x<=pos[19].x)
                                       pos[19].x+=1;
                                       else
                                       pos[19].x-=1;
                                       draw_board();
                                       printf("%f\n",sqrt(pow(pos[19].x-pos[i].x,2)+pow(pos[19].y-pos[i].y,2)));
                       }
      }                   
}     

void swapboard()
{
     int i;
     for(i=0;i<19;i++)
     {
                      pos[i].x=MAXX+2*MARGINX-pos[i].x;
                      pos[i].y=MAXY+2*MARGINY-pos[i].y;
     }
}

void player_change()
{                    
                       printf("P: %d,%d,%d\n",player,colour_white,colour_black);
                       if(player==white && colour_white==true && colour_black == false)
                       { 
                                        colour_white = false;
                                        colour_black = false;
                                        event= strikermove;
                                        striker_set();
                                        return;
                       }
                       
                       if ( player==black && colour_black==true && colour_white == false)
                       {
                            colour_white = false;
                            colour_black = false;
                            event = strikermove;
                            striker_set();
                            return; 
                       
                       }
                       player = player==white? black: white;
                      swapboard();
                      striker_set();
                       event= strikermove;   
                       colour_white = false;
                       colour_black = false;              
                              
} 

void hole()
{     int i; 
      for(i=0; i<20; i++)
      {if( sqrt(pow(MARGINX + MAXX/24 - pos[i].x,2) + pow( MARGINY + MAXY/24 - pos[i].y,2))< MAXX/20)
      {
      radius[i]=0;
      pos[i].x = pos[i].y=0; 
      vel[i].x = vel[i].y=0; 
      if(i<9)colour_white = true;
       else if(i<18) colour_black = true;
      }
      if( sqrt (pow(MARGINX + MAXX/24- pos[i].x,2)+ pow( MARGINY + MAXY - MAXY/24 - pos [i].y,2))<  MAXX/20)
      {
      radius[i]=0;
      pos[i].x = pos[i].y=0; 
      vel[i].x = vel[i].y=0;
      if(i<9)colour_white = true;
       else if(i<18) colour_black = true; 
      }
      if( sqrt ( pow( MARGINX +MAXX - MAXX/24 - pos [i].x,2)+ pow ( MARGINY + MAXY - MAXY/24 - pos[i].y,2))<  MAXX/20)
      {
      radius[i]=0;
      pos[i].x = pos[i].y=0; 
      vel[i].x = vel[i].y=0;
      if(i<9)colour_white = true;
       else if(i<18) colour_black = true; 
      }
      if (sqrt ( pow ( MARGINX + MAXX - MAXX/24 - pos[i].x,2)+ pow ( MARGINY + MAXY/24 - pos [i].y,2))< MAXX/20)
      {
      radius[i]=0;
      pos[i].x = pos[i].y=0; 
      vel[i].x = vel[i].y=0;
      if(i<9)colour_white = true;
       else if(i<18) colour_black = true; 
      }
      if(pos[19].x==0) radius[19]=MAXX/24;
       
      }
}         
void collision_update()
{
     int i,j; float temp,t1x,t2x,t1y,t2y,dist;
     int count = 0;
     
     for(i=0;i<20;i++)
     {
                     pos[i].x=pos[i].x+vel[i].x;
                     pos[i].y=pos[i].y+vel[i].y;
                     
                     if(sqrt(pow(vel[i].x,2)+pow(vel[i].y,2))<FRICTION/2)
                     {
                                                                         vel[i].x=0;vel[i].y=0;
                                                                         count++;
                                                                         continue;
                     }
                     vel[i].x-=vel[i].x*FRICTION/sqrt(pow(vel[i].x,2)+pow(vel[i].y,2));
                     vel[i].y-=vel[i].y*FRICTION/sqrt(pow(vel[i].x,2)+pow(vel[i].y,2));
                     
                     if(pos[i].x>=MARGINX+MAXX-radius[i])
                     {
                                                         vel[i].x=-vel[i].x;
                                                         pos[i].x=MARGINX+MAXX-radius[i];
                     }
     
                     if(pos[i].x<=MARGINX+radius[i])
                     {
                                                    vel[i].x=-vel[i].x;
                                                    pos[i].x=MARGINX+radius[i];
                     }
     
                     if(pos[i].y<=MARGINY+radius[i])
                     {
                                                    vel[i].y=-vel[i].y;
                                                    pos[i].y=MARGINY+radius[i];
                     }
     
                     if(pos[i].y>=MARGINY+MAXY-radius[i])
                     {
                                                         vel[i].y=-vel[i].y;
                                                         pos[i].y=MARGINY+MAXY-radius[i];
                     }
                     
                     for(j=0;j<20;j++)
                     {
                                       if(i==j)continue;
                                       dist=sqrt(pow(pos[i].x-pos[j].x,2)+pow(pos[i].y-pos[j].y,2));
                                       if(dist<radius[i]+radius[j])
                                       {
                                                                   pos[i].x+=0.5*(pos[i].x-pos[j].x)/dist;
                                                                   pos[i].y+=0.5*(pos[i].y-pos[j].y)/dist;
                                                                   pos[j].x-=(pos[i].x-pos[j].x)/dist;
                                                                   pos[j].y-=(pos[i].y-pos[j].y)/dist;
                                                                   
                                                                   t1x=(pos[i].x-pos[j].x)*vel[i].x+(pos[i].y-pos[j].y)*vel[i].y;
                                                                   t1y=(pos[i].x-pos[j].x)*vel[i].y-(pos[i].y-pos[j].y)*vel[i].x;
                                                                   t2x=(pos[i].x-pos[j].x)*vel[j].x+(pos[i].y-pos[j].y)*vel[j].y;
                                                                   t2y=(pos[i].x-pos[j].x)*vel[j].y-(pos[i].y-pos[j].y)*vel[j].x;
                                                                   
                                                                   vel[i].y=((pos[i].x-pos[j].x)*t1y+(pos[i].y-pos[j].y)*t2x)/(pow(radius[i]+radius[j],2));
                                                                   vel[i].x=((pos[i].x-pos[j].x)*t2x-(pos[i].y-pos[j].y)*t1y)/(pow(radius[i]+radius[j],2));
                                                                   vel[j].y=((pos[i].x-pos[j].x)*t2y+(pos[i].y-pos[j].y)*t1x)/(pow(radius[i]+radius[j],2));
                                                                   vel[j].x=((pos[i].x-pos[j].x)*t1x-(pos[i].y-pos[j].y)*t2y)/(pow(radius[i]+radius[j],2));
                                       }
                     }
     } 
     if(count == 20)
     {
           glutIdleFunc(NULL); player_change();
     }           
     draw_board();
     hole();
     sleep(10); 
}

void keypress(char ch, int x, int y)
{    
     int i,j;
       
     switch(event)
     {
                  case startgame: switch(ch)
                                  {  
                                       case 13: event=menu; printf("%d",event); break;
                                       case 27:exit(0);
                                  }break;
                  case menu:      switch(ch)
                                  {
                                       case(72||104):break;
                                       case 13: event=strikermove; printf("%d",event); break;
                                       case 27:exit(0);break;
                                  }break;
                  case direction: switch(ch)
                                  {
                                            case 37:cross.x-=2;
                                    if(cross.x<MARGINX) cross.x=MARGINX;
                                            case 39:cross.x+=2;
                                    if(cross.x>MARGINX+MAXX) cross.x=MARGINX+MAXX;
                                            case 38:cross.y-=2;
                                    if(cross.y<MARGINY) cross.y=MARGINY;
                                            case 40:cross.y+=2;
                                    if(cross.y>MARGINY+MAXY) cross.y=MARGINY+MAXY;
                                            case 13:event=powerfunc; break;
                                            case 27:exit(0);break;   
                                  }break;
                  case powerfunc: switch(ch)
                                  {
                                    case 's':power-=5;
                                if(power<=0) power=0; printf("%d",power); break;
                                    case 'w':power+=5;
                                if(power>=220) power=220;  printf("%d",power); break;
                                    case 13:vel[19].x=power/20*(-pos[19].x+cross.x)/sqrt(pow(pos[19].x-cross.x,2)+pow(pos[19].y-cross.y,2));
                                            vel[19].y=power/20*(-pos[19].y+cross.y)/sqrt(pow(pos[19].x-cross.x,2)+pow(pos[19].y-cross.y,2));
                                            //event=99; 
                                            glutIdleFunc(collision_update);break;
                                    case 27:exit(0);break;




                                }break;
                  case strikermove:switch(ch)
                                   {
                                   case 'a':pos[19].x-=2;
                                           if(pos[19].x<radius[19]+carrommargin+MARGINX+MAXX/50)
                                           pos[19].x=radius[19]+carrommargin+MARGINX+MAXX/50 ;
                                    
                                           for(i=0;i<19;i++)
                                           {
                                                    if(sqrt(pow(pos[19].x-pos[i].x,2)+pow(pos[19].y-pos[i].y,2))< radius[19]+radius[i])
                                                    {
                                                           if(pos[19].x-(2*(pos[19].x-pos[i].x))>=carrommargin + MARGINX+MAXX/50+radius[19])
                                                           pos[19].x-=2*(pos[19].x-pos[i].x);
                                                           else
                                                           pos[19].x+=2;
                                                    }
                                           }break;
                                    case 'd':pos[19].x+=2;
                                           if(pos[19].x>=MAXX+ MARGINX-carrommargin-MAXX/50-radius[19])
                                           pos[19].x=MAXX + MARGINX - carrommargin-MAXX/50-radius[19];
                                       
                                           for(i=0;i<19;i++)
                                           {
                                                    if(sqrt(pow(pos[19].x-pos[i].x,2)+pow(pos[19].y-pos[i].y,2))< radius[19]+radius[i])
                                                    {
                                                            if(pos[19].x+2*(pos[i].x-pos[19].x)<MAXX+MARGINX-carrommargin-MAXX/50-radius[19])
                                                            pos[19].x+=2*(pos[i].x-pos[19].x);
                                                            else
                                                            pos[19].x-=2;
                                                    }
                                           }break;      
                                    case 13: event=direction;
                                             cross.x=MARGINX+MAXX/2;
                                             cross.y=MARGINY+MAXY/2; break;
                                    case 27:exit(0); break;
                                }
      }
     draw_board();            
}

void key_spec(int ch, int x, int y)
{    
     int i,j;
       
     switch(event)
     {
                  case direction: switch(ch)
                                  {
                                            case 100:cross.x-=2;
                                    if(cross.x<MARGINX) cross.x=MARGINX;break;
                                            case 102:cross.x+=2;
                                    if(cross.x>MARGINX+MAXX) cross.x=MARGINX+MAXX;break;
                                            case 103:cross.y-=2;
                                    if(cross.y<MARGINY) cross.y=MARGINY;break;
                                            case 101:cross.y+=2;
                                    if(cross.y>MARGINY+MAXY) cross.y=MARGINY+MAXY;  break;
                                  }break;
                  case powerfunc: switch(ch)
                                  {
                                    case 103:power-=5;
                                if(power<=0) power=0; printf("%d",power); break;
                                    case 101:power+=5;
                                if(power>=220) power=220;  printf("%d",power); break;
                                }break;
                  case strikermove:switch(ch)
                                   {
                                   case 100:pos[19].x-=2;
                                           if(pos[19].x<radius[19]+carrommargin+MARGINX+MAXX/50)
                                           pos[19].x=radius[19]+carrommargin+MARGINX+MAXX/50 ;
                                    
                                           for(i=0;i<19;i++)
                                           {
                                                    if(sqrt(pow(pos[19].x-pos[i].x,2)+pow(pos[19].y-pos[i].y,2))< radius[19]+radius[i])
                                                    {
                                                           if(pos[19].x-(2*(pos[19].x-pos[i].x))>=carrommargin + MARGINX+MAXX/50+radius[19])
                                                           pos[19].x-=2*(pos[19].x-pos[i].x);
                                                           else
                                                           pos[19].x+=2;
                                                    }
                                           }break;
                                    case 102:pos[19].x+=2;
                                           if(pos[19].x>=MAXX+ MARGINX-carrommargin-MAXX/50-radius[19])
                                           pos[19].x=MAXX + MARGINX - carrommargin-MAXX/50-radius[19];
                                       
                                           for(i=0;i<19;i++)
                                           {
                                                    if(sqrt(pow(pos[19].x-pos[i].x,2)+pow(pos[19].y-pos[i].y,2))< radius[19]+radius[i])
                                                    {
                                                            if(pos[19].x+2*(pos[i].x-pos[19].x)<MAXX+MARGINX-carrommargin-MAXX/50-radius[19])
                                                            pos[19].x+=2*(pos[i].x-pos[19].x);
                                                            else
                                                            pos[19].x-=2;
                                                    }
                                           }break;
                                }
      }
     draw_board();            
}
void display( )
{
  static float i=0;                                  
  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);     /* clear the window */
 
  //glMatrixMode(GL_MODELVIEW);       /* The following coordinates are expressed */
  glLoadIdentity();                 /* in terms of World coordinates */
  glColor3f(1.0,1.0,1.0);
  glBegin(GL_POLYGON);
                     glVertex2f(100,100);
                     glVertex2f(200,100);
                     glVertex2f(200,200);
                     glVertex2f(100,200);
  glEnd();                   

  glutSwapBuffers();                     /* send all commands */
}       

int main(int argc,char **argv)
{
    glutInit(&argc,argv);
    glutInitWindowSize(640,480);
    glutInitWindowPosition(20,20);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
    glutCreateWindow("Screen");
    myinit();
    initialize();
    player_change();
    glutDisplayFunc(draw_board);
    glutKeyboardFunc(keypress);
    glutSpecialFunc(key_spec);
    glutIdleFunc(NULL);
    glutMainLoop();
}
